package com.dance.netty.nio.demo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.stream.Stream;

public class BufferAsScatteringAndGathering {

    public static void main(String[] args) throws IOException {

        /*
         * Scattering : 将数据写入Buffer时, 可以采用Buffer数组, 依次写入 [分散]
         * Gathering : 从Buffer读取数据时, 可以采用Buffer数组, 依次读取 [聚集]
         */

        // 使用 ServerSocketChannel 和 SocketChannel

        // 获取一个ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

        // 创建地址 地址默认为127.0.0.1 端口指定为 7000
        SocketAddress socketAddress = new InetSocketAddress(7000);

        // 绑定地址
        serverSocketChannel.socket().bind(socketAddress);

        // 创建Buffer数组
        ByteBuffer[] byteBuffers = new ByteBuffer[2];
        // 第一个容量为5
        byteBuffers[0] = ByteBuffer.allocate(5);
        // 第二个容量为3
        byteBuffers[1] = ByteBuffer.allocate(3);

        System.out.println("ServerSocketChannel stating in 7000.......");

        // 阻塞并等待连接
        SocketChannel socketChannel = serverSocketChannel.accept();

        // 定义消息长度
        int messageLength = 8;

        // 循环
        for (; ; ) {

            // 读取字节大小
            int byteReadSize = 0;

            // 只有小于 指定长度 才读取
            while (byteReadSize < messageLength) {
                // 修复BUG 在读取之前调用一下clear 不然第二次读取数据 readSize 会错误
                Arrays.stream(byteBuffers).forEach(ByteBuffer::clear);

                // 从通道读取到字节数组
                long readSize = socketChannel.read(byteBuffers);
                // 累计读取字节数量
                byteReadSize += readSize;
                System.out.println("byteReadSize: " + byteReadSize);
                // 打印字节数组中的Buffer中的position和limit
                Arrays.stream(byteBuffers).map(byteBuffer -> "buffer position: " + byteBuffer.position()
                                + " buffer limit: " + byteBuffer.limit() + "\t")
                        .forEach(System.out::print);
                System.out.println();
            }

            // 将Buffer数组中的Buffer做读写切换
            Arrays.stream(byteBuffers).forEach(ByteBuffer::flip);

            // 将接收到的数据回显给客户端
            int byteWriteSize = 0;

//            if (byteWriteSize < messageLength) {
                // 将数据写回到客户端
                long writeSize = socketChannel.write(byteBuffers);
                // 累计写出字节数量
                byteWriteSize += writeSize;

                // 修复BUG 补充上面逻辑,上面要累计到8 跳出,下面如果不够的话也需要跳出所以采用while不合理,所以取消条件
//            }

            // 清空字节数组中的Buffer
            Arrays.stream(byteBuffers).forEach(ByteBuffer::clear);

            // 打印统计
            System.out.println("byteReadSize: " + byteReadSize + ", byteWriteSize: " + byteWriteSize);

        }

    }

}
